home *** CD-ROM | disk | FTP | other *** search
/ SuperHack / SuperHack CD.bin / CODING / DELPHI / COMPRESS.ZIP / ARC2BLOB.PAS next >
Encoding:
Pascal/Delphi Source File  |  1996-04-02  |  4.9 KB  |  114 lines

  1. (*  ARC2BLOB.PAS  V2.0
  2.  
  3. This code is designed to be dropped into the COMPDEMO application, adding
  4. one new routine (LoadArchivedFileToBlobStream) and replacing one existing one
  5. (CDBImage1DragDrop).
  6.  
  7. It shows what is probably the most efficient way to load compressed data from
  8. a file archive to a blob field, without using an intermediate file as
  9. COMPDEMO currently does.
  10.  
  11. Keep in mind that both this and the ARC2MEM code require manipulation of some
  12. of the TCompress data structures... Unlike ARC2MEM, this approach doesn't
  13. require a large memory buffer (because no expansion step), but does require
  14. more knowledge of the TCompress data structures.
  15.  
  16. *)
  17.  
  18. { Example of Expanding a file DIRECTLY from an archive to a COMPRESSED field's blobstream.
  19.   Important note: we are NOT expanding the data at all, thus we are actually bypassing
  20.   all the expansion/compression stuff and writing directly to the underlying database }
  21. procedure TForm1.LoadArchivedFileToBlobStream(bs:TBlobstream;filepath:String);
  22. var fs: TFilestream;
  23.     cfinfo: TCompressedFileInfo;
  24.     fHeader: TCompressedFileHeader; { file header so we can get compression mode }
  25.     aheader: TCompressHeader;       { archive header required for Blobstream     }
  26.     cmode: string;
  27. begin
  28.   cfinfo := TCompressedFileInfo(FileList.objects[FileList.indexof(filepath)]);
  29.   fs:=TFileStream.Create(archivefile.text,fmOpenRead or fmShareExclusive); { just want to READ it... }
  30.   try
  31.      fs.read(aheader,sizeof(aheader));  { quick way to initialize archive header }
  32.      fs.seek(cfinfo.Position,0);        { start of FILE header within archive }
  33.      fs.read(fheader, sizeof(fheader)); { let's have it }
  34.      fs.seek(fheader.FilenameLength,1); { skip the filename which is stored next }
  35.  
  36.      { Now the tricky part -- we need to store a valid 3-char compression ID
  37.        in our archive header -- here's the best approach: }
  38.  
  39.      if fheader.compressedmode<>coNone then { coNone won't GET a header... }
  40.      begin
  41.        case fheader.compressedmode of
  42.           coLZH: cmode := 'LZH';
  43.           coRLE: cmode := 'RLE';
  44.           coCustom: cmode := 'CUS'; { CHANGE this if you use a different ID! }
  45.        end;
  46.        with aheader do  { ComID is already set by the read we did }
  47.        begin
  48.           Fullsize:=fheader.FullSize;
  49.           ArchiveType:=caSingle;
  50.           CheckSum := fheader.checksum;
  51.           Move(cmode[1],ComMethodID,sizeof(ComMethodID)); { get precisely the bytes we want... }
  52.        end;
  53.        bs.write(aheader,sizeof(aheader)); { set up the header }
  54.      end;
  55.      bs.copyFrom(fs,Fheader.compressedsize); { now get the raw (compressed) data! }
  56.      bs.truncate; { in case it started out larger... }
  57.   finally
  58.      fs.free
  59.   end;
  60. end;
  61.  
  62. { Examples of setting/loading/shifting image blobs using the above routine }
  63. procedure TForm1.CDBImage1DragDrop(Sender, Source: TObject; X, Y: Integer);
  64. var filepath: String;
  65.      cbs: TCBlobStream; { for loading image from an archived file }
  66. begin
  67.    if Source=Sender then exit; { nowt to do }
  68.    if (Sender is TCDBImage) and (not Table1.active) then
  69.    begin
  70.      showmessage('Can''t do this unless table has been opened...');
  71.      exit;
  72.    end;
  73.  
  74.   Screen.Cursor := crHourGlass;
  75.   if (Source is TImage) and (Sender is TCDBImage) then
  76.      CDBImage1.picture.bitmap.Assign(Image1.Picture.bitmap)
  77.   else if (Source is TCDBImage) and (Sender is TImage) then
  78.      Image1.picture.bitmap.Assign(CDBImage1.Picture.Bitmap)
  79.   else
  80.   begin   { Have we got an image? }
  81.      filepath := '';
  82.      if (Source is TListBox) and (Listbox1.selcount = 1) then
  83.       filepath:=ListBox1.Items[Listbox1.ItemIndex] { archive list }
  84.      else if (Source is TFileListBox) and (FL.selcount=1) then
  85.         filepath:=FL.Items[FL.ItemIndex]; { file list }
  86.      if ExtractFileExt(filepath)<>'.bmp' then
  87.         showmessage('Must be a .BMP file...')
  88.      else                                     { ok, here we go... }
  89.      if Source is TFileListBox then { just load from file... }
  90.        if Sender is TImage then
  91.           Image1.Picture.Bitmap.LoadFromfile(filepath)
  92.        else
  93.           CDBImage1.Picture.Bitmap.LoadFromFile(filepath)
  94.      else { source must be our archive file... }
  95.      begin
  96.        if Sender is TImage then
  97.            { Fastest way is using LoadArchivedFileToMemory approach per ARC2MEM.PAS }
  98.        else
  99.        begin { here is where we use our direct access routine... }
  100.          cbs:=TCBlobStream.Create(CDBImage1.CField,bmWrite);      { we ARE going to update but... }
  101.          try
  102.            LoadArchivedFileToBlobstream(cbs.Blobstream,filepath); { NOT via expansion/compression }
  103.          finally  { See the HELP notes on the Blobstream property for caveats }
  104.            cbs.free
  105.          end;
  106.        end
  107.      end;
  108.   end;
  109.   if Table1.active and Table1.Modified then Table1.post; { save immediately if updated }
  110.   if not Image1.Picture.Bitmap.Empty then Memo1.visible := False; { got a piccy showing... }
  111.   Screen.Cursor := crDefault;
  112. end;
  113.  
  114.